package myJs

import java.math.BigInteger
import myJs.ReRunMission.getCpuNum

import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.Utils._
import myJs.myPkg._
import org.scalajs.dom.Element
import org.scalajs.dom
import org.scalajs.dom._
import org.w3c.dom.html.HTMLSelectElement
import scalatags.Text.all._

import scala.scalajs.js.JSConverters._
import myJs.Implicits._
import shared.VarTool
import myJs.myPkg.bootstrap.Bootstrap.default._
import myPkg.jquery._
import org.scalajs.dom.ext.Ajax

import scala.scalajs.js.JSON
import scala.concurrent.ExecutionContext.Implicits.global
import japgolly.scalajs.react.component.Scala.Unmounted
import myJs.components.DiagnoseComponent
import org.scalajs.dom.raw.HTMLFormElement
import scalatags.Text.all

import scala.scalajs.js.Dynamic.{global => g}
import myJs.Implicits._

import scala.collection.immutable.SeqMap
import scala.collection.mutable

/**
 * Created by yz on 2019/4/25
 */
@JSExportTopLevel("NewMission")
object NewMission {

  val speciesData = mutable.LinkedHashMap(
    "Mammals" -> mutable.LinkedHashMap("hsa" -> "Homo sapiens  [80]",
      "mmu" -> "Mus musculus [82]",
      "rno" -> "Rattus norvegicus (rat)  [81]", "bta" -> "Bos taurus (cow)  [81]"),
    "Birds" -> mutable.LinkedHashMap("gga" -> "Gallus gallus (chicken)  [78]"),
    "Fish" -> mutable.LinkedHashMap("dre" -> "Danio rerio (zebrafish)  [81]"),
    "Insects" -> mutable.LinkedHashMap("dme" -> "Drosophila melanogaster (fruit fly)  [79]"),
    "Nematodes" -> mutable.LinkedHashMap("cel" -> "Caenorhabditis elegans (nematode)  [78]"),
    "Fungi" -> mutable.LinkedHashMap("sce" -> "Saccharomyces cerevisiae (yeast)  [65]"),
    "Plants" -> mutable.LinkedHashMap("osa" -> "Oryza sativa japonica (Japanese rice)  [83]",
      "ath" -> "Arabidopsis thaliana (thale cress)  [87]"),
    "Parasites" -> mutable.LinkedHashMap("smm" -> "Schistosoma mansoni  [69]",
      "pfa" -> "Plasmodium falciparum 3D7 (Malaria)  [47]",
      "tbr" -> "Trypanosoma brucei  [54]"),
    "Prokaryotes" -> mutable.LinkedHashMap("eco" -> "Escherichia coli K-12 MG1655  [87]",
      "bsu" -> "Bacillus subtilis  [80]",
      "ppu" -> "Pseudomonas putida KT2440  [89]", "sau" -> "Staphylococcus aureus N315 (MRSA/VSSA)  [73]",
      "tma" -> "Thermotoga maritima  [57]", "syf" -> "Synechococcus elongatus PCC7942  [75]",
      "mlo" -> "Mesorhizobium loti  [86]")
  )

  var idStr = ""

  var component: Unmounted[Unit, DiagnoseComponent.State, DiagnoseComponent.Backend]#Mounted = _

  @JSExport("init")
  def init = {
    component = DiagnoseComponent.Component().renderIntoDOM(document.querySelector(s"#diagnose"))

    getCpuNum { cpuNum =>
      bootStrapValidator(cpuNum)
    }
    fillSpecies
    val rs = speciesData.values.flatMap { map =>
      map.keySet
    }
    ReRunMission.enrichLibSelect
    refreshConfigSelect { () =>
      selectConfig
    }
    refreshReportHome()

    refreshTestOrder
    refreshDbId
    refreshUnit

    registerEvent

  }

  def registerEvent = {
    $(document.body).on("click", s".myRun", "", (y: Element) => {
      myRun
    })
  }

  def refreshUnit = {
    val rs = js.Array("μmol/L", "nmol/L", "μmol/g", "nmol/g", "nmol/million cells", "pmol/million cells", "ng/g",
      "μg/g")
    val jq = Tool.getInputByName("reportHome.unit")
    jq.typeahead(TypeaheadOptions.source(rs).showHintOnFocus(true).minLength(1).
      autoSelect(false))
  }

  var idNameTestPlatformMap = SeqMap[String, String]()

  def refreshTestOrder = {
    val url = g.jsRoutes.controllers.ToolController.getTestPlatform().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val dict = JSON.parse(xhr.responseText).toJDS
      idNameTestPlatformMap = dict.toSeqMap
      val orders = idNameTestPlatformMap.map { case (k, v) => s"${k}${v}" }.toJSArray
      val options = Select2Options.placeholder("选择一个Test Order").data(orders)
      Tool.getInputByName("testOrder").select2(options)
    }
  }

  def refreshDbId = {
    val url = g.jsRoutes.controllers.MetaboDbController.getAllMetaboDb().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArJDS.toList
      val array = (js.Dictionary("dbName" -> "默认库", "id" -> "0") :: (data)).map { dict =>
        js.Dictionary("text" -> dict("dbName"), "id" -> dict("id"))
      }
      val options = Select2Options.dictData(array.toJSArray)
      Tool.getInputByName("dbId").select2(options)
    }
  }

  @JSExport("testOrderChange")
  def testOrderChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    testOrderChangeByValue(myValue)
  }

  def testOrderChangeByValue(myValue: String) = {
    val idMap = idNameTestPlatformMap.map { case (k, v) =>
      s"${k}${v}" -> k
    }
    val nameMap = idNameTestPlatformMap.map { case (k, v) =>
      s"${k}${v}" -> v
    }
    val id = idMap(myValue)
    val name = nameMap(myValue)
    Tool.getInputByName("reportHome.testOrderName").`val`(name)
    Tool.getInputByName("reportHome.testOrderId").`val`(id)
  }

  def clearFile = {
    val curJq = Tool.getInputByName("dataXlsxFile", "dataCsvFile", "groupFile", "compareFile")
    curJq.fileinput("clear")
    val bv = $("#form").bv
    bv.revalidateField(curJq)
  }

  def myRun = {
    val bv = jQuery("#form").data("bootstrapValidator")
    bv.validate()
    val valid = bv.isValid().asInstanceOf[Boolean]
    if (valid) {
      val element = div(id := "content",
        span(id := "info", "正在检查文件",
          span(id := "progress", "。。。")), " ",
        img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
      ).render
      val index = layer.alert(element, Tool.layerOptions)
      fileCheck
    }
  }

  def fileCheck = {
    val formData = new FormData(document.getElementById("form").asInstanceOf[HTMLFormElement])
    val element = div(id := "content",
      span(id := "info", "正在上传数据文件",
        span(id := "progress", "。。。")), " ",
      img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
    ).render
    val index = layer.alert(element, Tool.layerOptions)
    val url = g.jsRoutes.controllers.MissionController.newMission().url.toString
    val xhr = new XMLHttpRequest
    xhr.open("post", url)
    xhr.upload.onprogress = progressHandlingFunction
    xhr.onreadystatechange = (e) => {
      if (xhr.readyState == XMLHttpRequest.DONE) {
        layer.close(index)
        val data = xhr.response
        val rs = JSON.parse(data.toString).toJDJAn
        val valid = rs("valid").asInstanceOf[Boolean]
        if (valid) {
          window.location.href = g.jsRoutes.controllers.UserController.missionManageBefore().url.toString
        } else {
          clearFile
          Swal.swal(SwalOptions.title("Error").text(rs.myGet("message")).`type`("error"))
        }
      }
    }
    xhr.send(formData)
  }


  def refreshConfigSelect(f: () => Any = () => ()) = {
    val url = g.jsRoutes.controllers.ConfigController.getAllNames().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(url).`type`("get").async(false).success { (data, status, e) =>
      val rs = data.asInstanceOf[js.Array[String]]
      val options = Select2Options.placeholder("选择一个参数方案").data(rs)
      $(":input[name='configName']").select2(options)
      f()
    }
    $.ajax(ajaxSettings)

  }

  def refreshReportHome(f: () => Any = () => ()) = {
    val url = g.jsRoutes.controllers.UserController.getUserById().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(url).`type`("get").async(false).success { (data, status, e) =>
      val rs = data.asInstanceOf[js.Dictionary[String]]
      $("#reportHome").hide()
      f()
    }
    $.ajax(ajaxSettings)
  }

  def selectConfig = {
    idStr = $(":input[name='hideConfigId']").`val`().toString
    if (idStr != "") {
      $(":input[name='configMode']").`val`("db").trigger("onchange")
      $(":input[name='configName']").`val`(idStr).select2().trigger("onchange")
    }
  }


  def fillSpecies = {
    val species = speciesData.keySet
    species.foreach { name =>
      val html = option(value := name, name)
      $("#selectSpecies1").append(html.toString())
    }
    val element = document.getElementById("selectSpecies1")
    change1(element)

  }

  @JSExport("change1")
  def change1(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    change1(myValue)
  }

  @JSExport("configChange")
  def configChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    configChangeByValue(myValue)
  }

  @JSExport("loessChange")
  def loessChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    loessChangeByValue(myValue)
  }


  @JSExport("configNameChange")
  def configNameChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    configNameChangeByValue(myValue)
  }

  @JSExport("colorModeChange")
  def colorModeChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    colorModeChangeByValue(myValue)
  }

  def colorModeChangeByValue(myValue: String) = {
    myValue match {
      case "file" =>
        $("#colorFile").show()
        $("#colorSolution").hide()
      case "db" =>
        $("#colorFile").hide()
        $("#colorSolution").show()
    }

  }

  def loessChangeByValue(myValue: String) = {
    myValue match {
      case "T" =>
        $(":input[name='isNormal']").`val`("F").attr("disabled", true)
      case _ =>
        $(":input[name='isNormal']").attr("disabled", false)
    }

  }

  @JSExport("replaceMethodChange")
  def replaceMethodChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    replaceMethodChangeByValue(myValue)
  }

  def replaceMethodChangeByValue(myValue: String) = {
    myValue match {
      case "knn" =>
        $("#knn").show()
        $("#min").hide()
      case x if List("min", "rowMin").contains(x) =>
        $("#knn").hide()
        $("#min").show()
      case _ =>
        $("#knn").hide()
        $("#min").hide()
    }

  }

  @JSExport("corChange")
  def corChange(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    corChangeByValue(myValue)
  }

  @JSExport("pathwayChange")
  def pathwayChange(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    if (myValue == "T") {
      $("#pathway").show()
    } else $("#pathway").hide()
  }

  @JSExport("speciesChange")
  def speciesChange(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    speciesChange(myValue)
  }

  def speciesChange(myValue: String): JQuery = {
    val isSmpData = if (List("hsa", "mmu").contains(myValue)) {
      Map("kegg" -> "KEGG", "smp" -> "SMPDB")
    } else Map("kegg" -> "KEGG")
    val isSmpHtml = isSmpData.map { case (fieldValue, text) =>
      option(value := fieldValue, text).render
    }.mkString("&nbsp;")
    $(":input[name='isSmp']").empty().html(isSmpHtml)
  }

  def change1(myValue: String): JQuery = {
    val map = speciesData(myValue)
    val html = map.map { case (fieldValue, text) =>
      option(value := fieldValue, text).render
    }.mkString("&nbsp;")
    $(":input[name='species']").empty().html(html)
    speciesChange(document.getElementById("species"))
  }

  def configChangeByValue(myValue: String) = {
    myValue match {
      case "db" => $("#configMode").show()
      case "hand" => $("#configMode").hide()
        $("#form").trigger("reset")
    }
  }

  def corChangeByValue(myValue: String) = {
    val idStr = "cor"
    myValue match {
      case "T" => $(s"#${idStr}").show()
        $(":input[name='cor.isParCorExec']").`val`("T").trigger("onchange")
      case "F" => $(s"#${idStr}").hide()
        $(":input[name='cor.isParCorExec']").`val`("F").trigger("onchange")
    }
  }

  @JSExport("parCorChange")
  def parCorChange(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    parCorChangeByValue(myValue)
  }

  def parCorChangeByValue(myValue: String) = {
    val idStr = "confounder"
    myValue match {
      case "T" => $(s"#${idStr}").show()
      case "F" => $(s"#${idStr}").hide()
    }
  }

  @JSExport("enrichChange")
  def enrichChange(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    enrichChangeByValue(myValue)
  }

  @JSExport("dataFileFormatChange")
  def dataFileFormatChange(y: Element): JQuery = {
    val myValue = $(y).find(">option:selected").`val`().toString
    dataFileFormatChangeByValue(myValue)
  }

  def dataFileFormatChangeByValue(myValue: String) = {
    myValue match {
      case "csv" =>
        $(s"#xlsxDataFile").hide()
        $(s"#csvDataFile").show()
      case "xlsx" =>
        $(s"#xlsxDataFile").show()
        $(s"#csvDataFile").hide()
    }
  }

  def enrichChangeByValue(myValue: String) = {
    val idStr = "enrich"
    myValue match {
      case "T" => $(s"#${idStr}").show()
      case "F" => $(s"#${idStr}").hide()
    }
  }


  def configNameChangeByValue(myValue: String) = {
    val url = g.jsRoutes.controllers.ConfigController.getConfig().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(s"${url}?id=${myValue}").`type`("get").async(false).success { (data, status, e) =>
      val rs = data.asInstanceOf[js.Dictionary[String]]

      val species = rs("species")
      val speciesKind = NewMission.speciesData.map { case (kind, map) =>
        (kind -> map.keySet)
      }.flatMap { case (kind, specieses) =>
        specieses.map((_ -> kind))
      }
      val kind = speciesKind(species)
      $("#selectSpecies1").`val`(kind).trigger("onchange")
      $(":input[name='species']").`val`(species).trigger("onchange")
      val names = $(".fillByName").mapElems { y =>
        $(y).attr("name").toString
      }.toArray
      Tool.fillByNames(rs, names)
      Tool.fillByNameAndTriggers(rs, List("diagnoseIsExec"))
      Tool.fillByNameAndTriggers(rs)
      val libTypes = rs("pathway.libTypes").split(";").toJSArray
      $(":input[name='pathway.libTypes[]']").`val`(libTypes).trigger("change")
    }
    $.ajax(ajaxSettings)

  }

  def bootStrapValidator(cpuNum: Int) = {
    val url = g.jsRoutes.controllers.MissionController.missionNameCheck().url.toString
    val maxNumber = Double.MaxValue
    val dict = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "dataXlsxFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "代谢数据文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "代谢数据文件格式不正确!",
              "extension" -> "xlsx",
            ),
          )
        ),
        "dataCsvFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "代谢数据文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "代谢数据文件格式不正确!",
              "extension" -> "csv",
            ),
          )
        ),
        "extraDataFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "额外数据矩阵文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "额外数据矩阵文件格式不正确!",
              "extension" -> "csv",
            ),
          )
        ),
        "confounderFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "confounder矩阵文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "confounder矩阵文件格式不正确!",
              "extension" -> "csv",
            ),
          )
        ),
        "groupFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "样品分组文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "样品分组文件格式不正确!",
              "extension" -> "csv",
            ),
          )
        ),
        "compareFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "比较配置文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "比较配置文件格式不正确!",
              "extension" -> "csv",
            ),
          )
        ),
        "sampleColorFile" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "分组颜色文件不能为空!"
            ),
            "file" -> js.Dictionary(
              "message" -> "分组颜色文件格式不正确!",
              "extension" -> "csv",
            ),
          )
        ),
        "missionName" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "任务名不能为空!"
            ),
            "remote" -> js.Dictionary(
              "message" -> "任务名已存在!",
              "extension" -> "csv",
              "url" -> url,
              "type" -> "POST",
              "delay" -> 1000
            ),
          )
        ),
        "diffMethod.pValue" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "p值阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "p值阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "p值阈值必须在0到1之间！",
            ),
          )
        ),
        "diffMethod.fdr" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "fdr阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "fdr阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "fdr阈值必须在0到1之间！",
            ),
          )
        ),
        "diffMethod.log2Fc" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "log2Fc阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "log2Fc阈值必须为数字!",
            ),
          )
        ),
        VarTool.vipName -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "vip值阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "vip值阈值必须为数字!",
            ),
          )
        ),
        VarTool.q2YName -> {
          val info = "Q2Y"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空!"
              ),
              "numeric" -> js.Dictionary(
                "message" -> s"${info}必须为数字!",
              ),
            )
          )
        },
        VarTool.q2YBName -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "Q2Y纵截距最大值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "Q2Y纵截距最大值必须为数字!",
            ),
          )
        ),
        "cor.coe" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "cor阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "cor阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "cor阈值必须在0到1之间！",
            ),
          )
        ),
        "cor.p" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "p值阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "p值阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "p值阈值必须在0到1之间！",
            ),
          )
        ),
        "cor.fdr" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "fdr阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "fdr阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "fdr阈值必须在0到1之间！",
            ),
          )
        ),
        "kwP" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "p值阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "p值阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "p值阈值必须在0到1之间！",
            ),
          )
        ),
        "diffMethod.kwFdr" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "fdr阈值不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "fdr阈值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> 1,
              "message" -> "fdr阈值必须在0到1之间！",
            ),
          )
        ),
        "diffTopN" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "top n不能为空!"
            ),
            "integer" -> js.Dictionary(
              "message" -> "top n必须为整数!",
            ),
            "between" -> js.Dictionary(
              "min" -> 1,
              "max" -> maxNumber,
              "message" -> "top n必须大于0！",
            ),
          )
        ),
        "rfTop" -> {
          val info = "RandomForest top n"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空!"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info}必须为整数!",
              ),
              "between" -> js.Dictionary(
                "min" -> 2,
                "max" -> maxNumber,
                "message" -> s"${info}必须大于1！",
              ),
            )
          )
        },
        "svmTop" -> {
          val info = "SVM top n"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空!"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info}必须为整数!",
              ),
              "between" -> js.Dictionary(
                "min" -> 2,
                "max" -> maxNumber,
                "message" -> s"${info}必须大于1！",
              ),
            )
          )
        },
        "seed" -> {
          val info = "Seed"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空!"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info}必须为整数!",
              ),
            )
          )
        },
        "borutaAfterTopN" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "Boruta执行后top n不能为空!"
            ),
            "integer" -> js.Dictionary(
              "message" -> "Boruta执行后top n必须为整数!",
            ),
            "between" -> js.Dictionary(
              "min" -> 2,
              "max" -> maxNumber,
              "message" -> "Boruta执行后top n必须大于1！",
            ),
          )
        ),
        "coef" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "coef不能为空!"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "coef必须为数字!",
            ),
          )
        ),
        "knn" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "k值不能为空!"
            ),
            "integer" -> js.Dictionary(
              "message" -> "k值必须为数字!",
            ),
            "between" -> js.Dictionary(
              "min" -> 1,
              "max" -> maxNumber,
              "message" -> "k值必须大于0！",
            ),
          )
        ),
        "threadNum" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "线程数不能为空！"
            ),
            "integer" -> js.Dictionary(
              "message" -> "线程数必须为整数！",
            ),
            "between" -> js.Dictionary(
              "min" -> 1,
              "max" -> cpuNum,
              "message" -> s"线程数必须大于0且小于等于${cpuNum}(服务器可用最大cpu)！",
            ),
          )
        ),
      )
    )
    g.$("#form").bootstrapValidator(dict)

  }

}
